# -*- coding: utf-8 -*-
'''
    :file: cloud.py
    :author: -Farmer
    :url: https://blog.farmer233.top
    :date: 2021/02/14 13:37:43
'''
from sqlalchemy.sql.expression import true
from app.models import User
import os
from flask.helpers import send_file, send_from_directory
from redis import ResponseError
from werkzeug.exceptions import NotFound
from app.utils import make_res
from flask import Blueprint, g, abort
from flask.globals import current_app, request
from flask_restful import Api, Resource
from app.extensions import auth
from app.operation.files import DownloadFile, FileOperation, ShareFile, UploadFile,\
    FileRename, MoveFile, MakeFolder
from app.operation.Spiders import DownloadSpider
from app.operation.zips import UnZipFile

cloud_bp = Blueprint('cloud', __name__)
api = Api(cloud_bp)

# 获取文件列表接口
class GetFilesInfoView(Resource):
    decorators = [auth.login_required]

    def post(self):
        req_data = request.get_json()
        try:
            path = req_data.get('path')
            files = FileOperation(g.username)
            datas = files.get_file(path=path)
            return make_res(data=datas)
        except AttributeError as e:
            current_app.logger.warning(e)
            return make_res(code=-1, message='请传递json参数')
        except Exception as e:
            current_app.logger.error(e)
            return make_res(code=-1, message=str(e))

# 上传文件接口
class UploadFileView(Resource):
    decorators = [auth.login_required]

    def post(self):
        try:
            path = request.form.get("path")
            file = request.files.get("file")
            if file is None or path is None:
                return make_res(code=-1, message="缺失必要参数")
            fileop = UploadFile(g.username)
            upload_msg = fileop.upload(path=path, file=file)
            return make_res(message="上传成功", data=upload_msg)
        except ValueError as e:
            current_app.logger.info(e)
            return make_res(code=-1, message=str(e))
        except Exception as e:
            current_app.logger.error(e)
            return make_res(code=-9, message=str(e))

# 下载文件接口（ajax实现）不建议使用
class DownloadFileView(Resource):
    decorators = [auth.login_required]

    def get(self, path):
        try:
            file = DownloadFile(g.username, path)
            file_path, filename = file.get_file()
            # return send_from_directory(file_path, filename)
            return send_from_directory(file_path, filename, as_attachment=True)
        except ValueError as e:
            current_app.logger.info(e)
            return make_res(code=-1, message=str(e))
        except Exception as e:
            current_app.logger.error(e)
            return make_res(code=-1, message=str(e))

# 离线下载接口
class OutsideDownloadView(Resource):
    decorators = [auth.login_required]

    def post(self):
        try:
            req_data = request.get_json()
            download_url = req_data.get("url")
            download_path = req_data.get("path", "./")
            
            download = DownloadSpider(g.username)
            download = download.download(
                get_url=download_url, save_path=download_path)

            return make_res(message="下载线程已启动，正在下载")
        except ValueError as e:
            current_app.logger.info(e)
            return make_res(code=-1, message=str(e))
        except Exception as e:
            current_app.logger.warning(e)
            return make_res(code=-9, message=str(e))

# 重命名接口
class RenameView(Resource):
    decorators = [auth.login_required]

    def post(self):
        try:
            req_data = request.get_json()
            path = req_data.get('path')
            old_name = req_data.get('old_name')
            new_name = req_data.get("new_name")

            if path is None or old_name is None or new_name is None:
                return make_res(code=-1, message="缺失必要参数")

            rename = FileRename(g.username)
            rename.rename(path=path, old_name=old_name, new_name=new_name)
            return make_res()
        except FileNotFoundError as e:
            current_app.logger.info(e)
            return make_res(code=-1, message="重命名失败，找不到文件")
        except ValueError as e:
            current_app.logger.info(e)
            return make_res(code=-1, message=str(e))
        except Exception as e:
            current_app.logger.warning(e)
            return make_res(code=-9, message=str(e))

# 移动文件接口
class MoveFileView(Resource):
    decorators = [auth.login_required]

    def post(self):
        try:
            req_data = request.get_json()
            path = req_data.get('path')
            filename = req_data.get('filename')
            new_path = req_data.get('new_path')
            if path is None or filename is None or new_path is None:
                return make_res(code=-1, message="缺失必要参数")

            file = MoveFile(g.username)
            file.move(new_path=new_path, old_path=path, filename=filename)
            return make_res(message="移动文件完成", data={
                "pre_path": path,
                "now_path": new_path,
                "filename": filename
            })
        except ValueError as e:
            current_app.logger.info(e)
            return make_res(code=-1, message=str(e))
        except FileNotFoundError as e:
            current_app.logger.info(e)
            return make_res(code=-1, message="移动失败，文件不存在")
        except Exception as e:
            current_app.logger.warning(e)
            return make_res(code=-9, message=str(e))

# 生成文件夹接口
class MakeFolderView(Resource):
    decorators = [auth.login_required]

    def post(self):
        try:
            req_data = request.get_json()
            path = req_data.get('path')
            folder_name = req_data.get('folder_name')
            if path is None or folder_name is None:
                return make_res(code=-1, message="缺失必要参数")

            file = MakeFolder(g.username)
            file.make(path, folder_name)
            return make_res(data=req_data)
        except ValueError as e:
            current_app.logger.info(e)
            return make_res(code=-1, message=str(e))
        except FileNotFoundError as e:
            current_app.logger.info(e)
            return make_res(code=-1, message="移动失败，文件不存在")
        except Exception as e:
            current_app.logger.warning(e)
            return make_res(code=-9, message=str(e))

# 分享文件接口
class ShareView(Resource):
    decorators = [auth.login_required]

    def post(self):
        try:
            req_data = request.get_json()
            path = req_data.get('path')
            filename = req_data.get('filename')
            timeout = req_data.get('timeout')
            if path is None or filename is None or timeout is None:
                return make_res(code=-1, message="缺失必要参数")

            share_file = ShareFile(g.username)
            share_msg = share_file.make_share_code(path, filename, timeout)
            return make_res(data=share_msg)
        except ResponseError as e:
            current_app.logger.info(e)
            return make_res(code=-1, message="时间请输入整数")
        except ConnectionError as e:
            current_app.logger.warning(e)
            return make_res(code=-1, message="redis服务器连接失败")
        except FileNotFoundError as e:
            current_app.logger.info(e)
            return make_res(code=-1, message="移动失败，文件不存在")
        except Exception as e:
            current_app.logger.warning(e)
            return make_res(code=-9, message=str(e))

# 下载分享文件接口
class DownloadShareView(Resource):
    def get(self):
        try:
            code = request.args.get('share_code', None)
            if code is None:
                abort(404)
            path, filename = ShareFile().download_share_file(share_code=code)
            print(path, filename)
            filepath = os.path.join(path, filename)
            return send_file(filename_or_fp=filepath, as_attachment=True, add_etags=True, conditional=True)
            return send_from_directory(path, filename, as_attachment=True)
        except ValueError as e:
            current_app.logger.info(e)
            return make_res(code=-1, message=str(e))
        except NotFound as e:
            current_app.logger.info(e)
            return make_res(code=-4, message="分享码不存在")
        except Exception as e:
            current_app.logger.warning(e)
            return make_res(code=-9, message=str(e))

# 解压、压缩文件接口
class ZipFileView(Resource):
    decorators = [auth.login_required]

    def post(self):
        try:
            req_data = request.get_json()
            zip_type = req_data.get('type')
            path = req_data.get('path')
            filename = req_data.get('filename')
            if zip_type is None or path is None or filename is None:
                return make_res(code=-1, message="缺失必要参数")
            if zip_type == "unzip":
                return self.unzip(path, filename)
            else:
                return make_res(code=-1, message="类型错误")
        except ValueError as e:
            current_app.logger.info(e)
            return make_res(code=-1, message=str(e))
        except FileNotFoundError as e:
            current_app.logger.info(e)
            return make_res(code=-1, message="文件不存在")
        except Exception as e:
            print(type(e))
            current_app.logger.warning(e)
            return make_res(code=-9, message=str(e))

    def unzip(self, path, filename):
        zip_file = UnZipFile(g.username)
        path = zip_file.unzip(path=path, filename=filename)
        return {"path": path}

# 游客分享文件接口
class GuestShareView(Resource):
    def get(self):
        pass

    def post(self):
        try:
            # 文件上传部分👇
            path = './'
            file = request.files.get("file")
            # 游客分享文件放在guest文件夹中
            guest = User.query.filter(User.username == 'guest').first()

            if file is None or path is None:
                return make_res(code=-1, message="缺失必要参数")
            
            fileop = UploadFile(guest.username)
            upload_msg = fileop.upload(path=path, file=file)

            # 生成分享码部分👇
            filename = upload_msg.get('filename')
            timeout = 1
            if filename is None:
                return make_res(code=-1, message="保存失败")
            
            share_file = ShareFile(guest.username)
            share_msg = share_file.make_share_code(path, filename, timeout)

            return make_res(data=share_msg)
        except ResponseError as e:
            current_app.logger.info(e)
            return make_res(code=-1, message="时间请输入整数")
        except ConnectionError as e:
            current_app.logger.warning(e)
            return make_res(code=-1, message="redis服务器连接失败")
        except FileNotFoundError as e:
            current_app.logger.info(e)
            return make_res(code=-1, message="路径不存在")
        except Exception as e:
            current_app.logger.warning(e)
            return make_res(code=-9, message=str(e))


# 删除文件接口
class DelFileView(Resource):
    decorators = [auth.login_required]
    def post(self):
        try:
            req = request.get_json()
            path = req.get('path')
            filename = req.get('filename')
            file = FileOperation(g.username)
            resp = file.del_file(path=path, filename=filename)
            return make_res(message=resp)
        except Exception as e:
            print(e)

api.add_resource(GetFilesInfoView, '/getInfo')
api.add_resource(UploadFileView, "/upload")
api.add_resource(DownloadFileView, "/download/<path:path>")
api.add_resource(OutsideDownloadView, "/offline_download")
api.add_resource(RenameView, "/rename")
api.add_resource(MoveFileView, "/move")
api.add_resource(MakeFolderView, '/make_folder')
api.add_resource(ShareView, "/get_share")
api.add_resource(DownloadShareView, "/download_share")
# 压缩、解压接口
api.add_resource(ZipFileView, "/zipfile")
# del
api.add_resource(DelFileView, '/del')
# guest
api.add_resource(GuestShareView, '/guest')